package jsonrepo

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"rc/repo/model"
	"rc/utils"
	"strings"
)

type jsonRepo struct {
	repoPath string
	groups   []model.NodeGroup
}

func InitRepo(repoPath string) (*jsonRepo, error) {
	var (
		groups []model.NodeGroup
		bytes  []byte
		err    error
	)

	repoPath, err = utils.ConvertHomeDir(repoPath)
	if err != nil {
		return nil, err
	}

	bytes, err = ioutil.ReadFile(repoPath)
	if err != nil {
		return nil, err
	}

	if err = json.Unmarshal(bytes, &groups); err != nil {
		return nil, err
	}

	return &jsonRepo{
		repoPath: repoPath,
		groups:   groups,
	}, err
}

// merge group user_infos to node user_infos
func mergeUserInfos(gUserInfos, nUserInfos []model.UserInfo) []model.UserInfo {
	var mUserInfo = make(map[string]model.UserInfo)

	if gUserInfos != nil && len(gUserInfos) > 0 {
		for _, ui := range gUserInfos {
			mUserInfo[ui.UserName+"-"+ui.Password+"-"+ui.KeyPath] = ui
		}
	}

	if nUserInfos != nil && len(nUserInfos) > 0 {
		for _, ui := range nUserInfos {
			mUserInfo[ui.UserName+"-"+ui.Password+"-"+ui.KeyPath] = ui
		}
	}

	var userInfos = make([]model.UserInfo, 0)
	for _, v := range mUserInfo {
		userInfos = append(userInfos, v)
	}

	return userInfos
}

// =========== implement interface repo =======================

func (jr *jsonRepo) GetNodeGroups(name string) ([]model.NodeGroup, error) {
	var filterGroups = make([]model.NodeGroup, 0)
	for _, g := range jr.groups {
		if strings.Index(g.Name, name) >= 0 {
			filterGroups = append(filterGroups, g)
		}
	}

	if len(filterGroups) == 0 {
		return nil, fmt.Errorf("Not found *NODEGROUP*")
	}
	return filterGroups, nil
}

func (jr *jsonRepo) GetFirstNodeGroup(name string) (model.NodeGroup, error) {
	var groups, err = jr.GetNodeGroups(name)
	if err != nil {
		return model.NodeGroup{}, err
	}

	return groups[0], nil
}

func (jr *jsonRepo) GetNodes(name string, groupName string) ([]model.Node, error) {
	nodes, _, err := jr.GetNodesWithGroupName(name, groupName)
	return nodes, err
}

func (jr *jsonRepo) GetFirstNode(name string, groupName string) (model.Node, error) {
	var nodes, err = jr.GetNodes(name, groupName)
	if err != nil {
		return model.Node{}, err
	}

	return nodes[0], nil
}

func (jr *jsonRepo) GetNodesWithGroupName(name string, groupName string) ([]model.Node, []string, error) {
	var filterNodes = make([]model.Node, 0)
	var groupNames = make([]string, 0)

	var filterGroups, err = jr.GetNodeGroups(groupName)
	if err != nil {
		return nil, nil, err
	}

	for _, g := range filterGroups {
		if g.Nodes == nil {
			continue
		}

		for _, n := range g.Nodes {
			if strings.Index(n.Name, name) >= 0 {
				n.UserInfos = mergeUserInfos(g.UserInfos, n.UserInfos)
				filterNodes = append(filterNodes, n)
				groupNames = append(groupNames, g.Name)
			}
		}
	}

	if len(filterNodes) == 0 {
		return nil, nil, fmt.Errorf("Not found *NODE*")
	}
	return filterNodes, groupNames, nil
}
